import openpyxl
from openpyxl.styles import Font, Border, Side, Alignment, PatternFill, Protection
from openpyxl.drawing.image import Image
from PIL import JpegImagePlugin

JpegImagePlugin._getmp = lambda x: None


class Excel_Option:
    def __init__(self, file_path):
        self.file_path = file_path
        self.workbook = None

    def __del__(self):
        self.close_file()

    # 打开文件
    def open_file(self, read_only=False, data_only=True, keep_links=True):
        """
        打开文件
        :param read_only: 是否只读
        :param data_only: 是否保存公式
        :param rich_text: 是否保存指向外部工作簿的链接
        :return: 是否打开成功
        """
        try:
            self.workbook = openpyxl.load_workbook(self.file_path,
                                                   read_only=read_only,
                                                   data_only=data_only,
                                                   keep_links=keep_links,
                                                   )
            # # 解除所有单元格的锁定
            # for sheet in self.workbook:
            #     for row in sheet.iter_rows():
            #         for cell in row:
            #             if hasattr(cell, 'protection'):
            #                 cell.protection.locked = False
            return True
        except Exception as e:
            print(f"打开{self.file_path}失败，请查看：{e}")
            return False

    # 关闭文件
    def close_file(self):
        """
        关闭文件
        :return:
        """
        try:
            if self.workbook is not None:
                self.workbook.close()
                # print(f"关闭{self.file_path}成功！")
                return True
            else:
                print(f"未打开{self.file_path}，无需关闭！")
                return False
        except Exception as e:
            print(f"关闭{self.file_path}失败！请查看：{e}")
            return False

    # 创建新文件
    def create_new_excel(self):
        """
        创建新的 Excel 表
        """
        self.workbook = openpyxl.Workbook()
        return True

    # 保存文件
    def save_file(self, file_name=None):
        """
        保存文件
        :param file_name:默认为打开的文件，如需另存，请填写file_name
        :return:
        """
        try:
            if self.workbook is not None:
                if file_name is None:
                    self.workbook.save(self.file_path)
                    # print(f"保存{self.file_path}成功！")
                    return True
                else:
                    self.workbook.save(file_name)
                    # print(f"保存{file_name}成功！")
                    return True
            else:
                print(f"未创建excel文件，不能保存！")
        except Exception as e:
            print(f"保存失败，请查看：{e}")

    # 获取当前的获得sheet
    def get_current_sheet(self):
        """
        获取当前的活动sheet
        :return:返回sheet名称
        """
        return self.workbook.active.title

    # 列出所有的sheet
    def list_sheets(self):
        """
        列出工作簿中的所有的sheet
        :return:列表格式的sheet
        """
        return self.workbook.sheetnames

    # 切换至指定的sheet
    def change_active_sheet(self, sheet_name):
        """
        切换至指定的sheet
        :param sheet_name: sheet名
        :return:
        """
        try:
            if sheet_name in self.list_sheets():
                self.workbook.active = self.workbook[sheet_name]
                return True
            else:
                return False
        except Exception as e:
            print(f"切换活动sheet失败！请查看：{e}")

    # 创建新的sheet
    def create_new_sheet(self, sheet_name):
        """
        创建新的sheet
        :param sheet_name: sheet名称
        :return: 是否创建成功
        """
        try:
            if sheet_name not in self.list_sheets():
                self.workbook.create_sheet(sheet_name)
                return True
            else:
                print(f"工作簿中已存在名为 {sheet_name} 的sheet")
                return False
        except Exception as e:
            print(f"创建sheet {sheet_name} 失败！请查看：{e}")
            return False

    # 删除sheet
    def delete_sheet(self, sheet_name):
        """
        删除指定的sheet
        :param sheet_name: sheet名称
        :return: 是否删除成功
        """
        try:
            if sheet_name in self.list_sheets():
                self.workbook.remove(self.workbook[sheet_name])
                return True
            else:
                print(f"工作簿中不存在名为 {sheet_name} 的sheet")
                return False
        except Exception as e:
            print(f"删除sheet {sheet_name} 失败！请查看：{e}")
            return False

    # 修改sheet名称
    def modify_sheet_name(self, old_sheet_name, new_sheet_name):
        """
        修改sheet名称
        :param old_sheet_name: 原sheet名称
        :param new_sheet_name: 新sheet名称
        :return: 是否修改成功
        """
        try:
            if old_sheet_name in self.list_sheets():
                sheet = self.workbook[old_sheet_name]
                sheet.title = new_sheet_name
                return True
            else:
                print(f"工作簿中不存在名为 {old_sheet_name} 的sheet")
                return False
        except Exception as e:
            print(f"修改sheet名称失败！请查看：{e}")
            return False

    # 获取sheet中的表头headers
    def get_sheet_headers(self, sheet_name=None, row: int = 1):
        """
        获取sheet中的表头headers
        :param sheet_name: 默认None，为当前。如果需要指定，请填写sheet_name
        :param row: 默认1，指定以第几行作为表头
        :return: 列表表头
        """
        if sheet_name is None:
            sheet = self.workbook[self.get_current_sheet()]
        else:
            sheet = self.workbook[sheet_name]
        return [cell.value for cell in sheet[row]]

    # 获取sheet的最大行数
    def get_sheet_max_rows(self, sheet_name=None):
        """
        获取sheet的最大行数
        :param sheet_name:  默认None，为当前。如果需要指定，请填写sheet_name
        :return: 最大行数
        """
        if sheet_name is None:
            sheet = self.workbook[self.get_current_sheet()]
        else:
            sheet = self.workbook[sheet_name]
        return sheet.max_row

    # 将字母表示的列名转换为数字序号
    def convert_to_number(self, column_letter):
        """
        将字母表示的列名转换为数字序号
        :param column_letter: 字母表示的列名，例如 "A"、"C"、"AA" 等形式
        :return: 对应的数字序号，若输入格式有误返回None
        """
        num = 0
        column_letter = column_letter.upper()
        length = len(column_letter)
        for i in range(length):
            num = num * 26 + (ord(column_letter[i]) - ord('A') + 1)
        return num

    # 获取指定的单元格值
    def get_cell_value(self, sheet_name, row, col):
        """
        获取指定的单元格值
        :param sheet_name: 要获取单元格所在的工作表名称
        :param row: 单元格所在的行号（从1开始计数）,可以是‘A’这种格式
        :param col: 单元格所在的列号（从1开始计数，可以是数字也可以是字母表示，如1表示A列，2表示B列等）
        :return: 返回指定单元格的值，如果单元格不存在等情况返回None
        """
        try:
            if sheet_name in self.list_sheets():
                sheet = self.workbook[sheet_name]
                cell = sheet.cell(row=row, column=col)
                return cell.value
            else:
                print(f"工作簿中不存在名为 {sheet_name} 的sheet")
                return None
        except Exception as e:
            print(f"获取单元格值失败，请查看：{e}")
            return None

    # 获取列值
    def get_column_values(self, sheet_name, column_identifier):
        """
         获取指定列的所有单元格的值
         :param sheet_name: 要获取列值所在的工作表名称
         :param column_identifier: 列的标识，可以是字母表示（如"A"）也可以是数字序号（如1表示A列）
         :return: 返回指定列所有单元格值组成的列表，如果工作表或列不存在等情况返回空列表
         """
        column_values = []
        try:
            if sheet_name in self.list_sheets():
                sheet = self.workbook[sheet_name]
                # 判断传入的列标识是字母还是数字
                if isinstance(column_identifier, str):
                    column_index = self.convert_to_number(column_identifier)
                else:
                    column_index = column_identifier
                for row in sheet.rows:
                    cell = row[column_index - 1]
                    column_values.append(cell.value)
            return column_values
        except Exception as e:
            print(f"获取列值失败，请查看：{e}")
            return []

    # 获取指定的行值
    def get_row_values_as_dict(self, sheet_name, row_number):
        """
        获取指定行的所有单元格的值，并结合表头信息以字典形式返回
        :param sheet_name: 要获取行值所在的工作表名称
        :param row_number: 行号，从1开始计数
        :return: 返回一个字典，键为表头（列名），值为对应列在指定行的单元格的值，如果工作表或行不存在等情况返回空字典
        """
        result_dict = {}
        try:
            # 检查工作表是否存在
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return result_dict

            sheet = self.workbook[sheet_name]

            # 获取表头信息
            headers = self.get_sheet_headers(sheet_name)

            # 检查行号是否有效
            if row_number < 1 or row_number > sheet.max_row:
                print(f"指定的行号 {row_number} 超出有效范围")
                return result_dict

            # 获取指定行的单元格
            row_cells = sheet[row_number]

            # 将表头和对应单元格的值组合成字典
            for header, cell in zip(headers, row_cells):
                result_dict[header] = cell.value

            return result_dict
        except Exception as e:
            print(f"获取行值并转换为字典时出现异常，请查看：{e}")
            return result_dict

    # 修改指定的单元格值
    def modify_cell_value(self, sheet_name, row, col, new_value):
        """
        修改指定的单元格值
        :param sheet_name: 要修改单元格所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param row: 单元格所在的行号（从1开始计数）
        :param col: 单元格所在的列号（从1开始计数）
        :param new_value: 要设置的新值
        :return: 如果修改成功返回True，若工作表或单元格不存在等情况返回False
        """
        try:
            if sheet_name in self.list_sheets():
                sheet = self.workbook[sheet_name]
                cell = sheet.cell(row=row, column=col)
                cell.value = new_value
                return True
            else:
                print(f"工作簿中不存在名为 {sheet_name} 的sheet")
                return False
        except Exception as e:
            print(f"修改单元格值失败，请查看：{e}")
            return False

    # 修改指定的列值
    def modify_column_values(self, sheet_name, column_identifier, new_values_list):
        """
        修改指定列的所有单元格的值
        :param sheet_name: 要修改列值所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param column_identifier: 列的标识，可以是字母表示（如"A"）也可以是数字序号（如1表示A列）
        :param new_values_list: 包含新值的列表，列表长度应与指定列的单元格数量匹配（或小于等于，若小于则只修改对应位置的单元格），列表中的元素为对应单元格要设置的新值
        :return: 如果修改成功返回True，若工作表不存在、列标识无效或者新值列表长度不匹配等情况返回False
        """
        try:
            # 检查工作表是否存在
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 将列标识转换为数字索引（列序号从1开始计数）
            if isinstance(column_identifier, str):
                column_index = self.convert_to_number(column_identifier)
            else:
                column_index = column_identifier
            if column_index is None:
                print(f"无效的列标识 {column_identifier}")
                return False

            # 检查新值列表长度与列单元格数量的匹配情况
            max_row = sheet.max_row
            if len(new_values_list) > max_row:
                print(f"新值列表长度大于指定列的单元格数量，无法完成修改")
                return False

            # 遍历行来修改指定列的单元格值
            for row_num in range(1, max_row + 1):
                cell = sheet.cell(row=row_num, column=column_index)
                if row_num - 1 < len(new_values_list):
                    cell.value = new_values_list[row_num - 1]
            return True
        except Exception as e:
            print(f"修改列值时出现异常，请查看：{e}")
            return False

    # 修改指定的行值
    def modify_row_values(self, sheet_name, row_number, new_values_dict):
        """
        修改指定行的所有单元格的值，用户参数是字典，字典键为列名（表头），值为对应列要设置的新值
        :param sheet_name: 要修改行值所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param row_number: 行号，从1开始计数
        :param new_values_dict: 包含新值的字典，键为列名（表头），值为对应列在指定行要设置的新值
        :return: 如果修改成功返回True，若工作表不存在、行号无效或者表头与列不匹配等情况返回False
        """
        try:
            # 检查工作表是否存在
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 检查行号是否有效
            if row_number < 1 or row_number > sheet.max_row:
                print(f"指定的行号 {row_number} 超出有效范围")
                return False

            # 获取表头信息
            headers = self.get_sheet_headers(sheet_name)

            # 遍历表头和对应单元格，根据字典修改值
            for header in headers:
                if header in new_values_dict:
                    col_index = None
                    for col_num in range(1, len(headers) + 1):
                        cell = sheet.cell(row=1, column=col_num)
                        if cell.value == header:
                            col_index = col_num
                            break
                    if col_index is not None:
                        cell_to_modify = sheet.cell(row=row_number, column=col_index)
                        cell_to_modify.value = new_values_dict[header]

            return True
        except Exception as e:
            print(f"修改行值时出现异常，请查看：{e}")
            return False

    # 插入制定的行值
    def insert_row_values(self, sheet_name, row_number, new_values_dict):
        """
        在指定工作表的指定行号位置插入一行数据，用户传入包含要插入值的字典，字典键为列名（表头），值为对应列要插入的新值。
        :param sheet_name: 要插入行所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中。
        :param row_number: 行号，从1开始计数，表示要在该行之前插入新行。
        :param new_values_dict: 包含要插入单元格值的字典，键为列名（表头），值为对应列在新行要插入的新值。
        :return: 如果插入成功返回True，若工作表不存在、行号无效或者表头与列不匹配等情况返回False。
        """
        try:
            # 检查工作表是否存在
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            """
            # 检查行号是否有效（可根据实际需求决定是否启用这部分检查，例如允许在末尾追加行时可不做上限检查）
            if row_number < 1 or row_number > sheet.max_row + 1:
                print(f"指定的行号 {row_number} 超出有效范围")
                return False
            """
            # 获取表头信息
            headers = self.get_sheet_headers(sheet_name)

            # 插入新行，需要先将现有行向下移动一行
            sheet.insert_rows(row_number)

            # 遍历表头和新值字典，将值插入到新行对应列
            for header in headers:
                self.modify_cell_value(sheet_name, row_number, headers.index(header) + 1, new_values_dict.get(header))

            return True
        except Exception as e:
            print(f"插入行值时出现异常，请查看：{e}")
            return False

    # 在指定列插入列
    def insert_column(self, sheet_name, column_identifier, num_columns=1):
        """
        在指定列插入新列
        :param sheet_name: 要插入列所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param column_identifier: 列的标识，可以是字母表示（如"A"）也可以是数字序号（如1表示A列）
        :param num_columns: 要插入的列的数量，默认值为1
        :return: 如果插入成功返回True，若工作表不存在、列标识无效等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 将列标识转换为数字索引（列序号从1开始计数）
            if isinstance(column_identifier, str):
                column_index = self.convert_to_number(column_identifier)
            else:
                column_index = column_identifier
            if column_index is None:
                print(f"无效的列标识 {column_identifier}")
                return False

            # 在指定列插入指定数量的列
            for _ in range(num_columns):
                sheet.insert_cols(column_index)
            return True
        except Exception as e:
            print(f"插入列时出现异常，请查看：{e}")
            return False

    # 在指定行插入行
    def insert_row(self, sheet_name, row_number, num_rows=1):
        """
        在指定行插入新行
        :param sheet_name: 要插入行所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param row_number: 行号，从1开始计数，新行将插入在此行之前
        :param num_rows: 要插入的行的数量，默认值为1
        :return: 如果插入成功返回True，若工作表不存在、行号无效等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 检查行号是否有效
            if row_number < 1 or row_number > sheet.max_row + 1:
                print(f"指定的行号 {row_number} 超出有效范围")
                return False

            # 在指定行插入指定数量的行
            for _ in range(num_rows):
                sheet.insert_rows(row_number)
            return True
        except Exception as e:
            print(f"插入行时出现异常，请查看：{e}")
            return False

    # 删除指定列
    def delete_column(self, sheet_name, column_identifier):
        """
        删除指定列
        :param sheet_name: 要删除列所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param column_identifier: 列的标识，可以是字母表示（如"A"）也可以是数字序号（如1表示A列）
        :return: 如果删除成功返回True，若工作表不存在、列标识无效等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 将列标识转换为数字索引（列序号从1开始计数）
            if isinstance(column_identifier, str):
                column_index = self.convert_to_number(column_identifier)
            else:
                column_index = column_identifier
            if column_index is None:
                print(f"无效的列标识 {column_identifier}")
                return False

            # 删除指定列
            sheet.delete_cols(column_index)
            return True
        except Exception as e:
            print(f"删除列时出现异常，请查看：{e}")
            return False

    # 删除指定行
    def delete_row(self, sheet_name, row_number):
        """
        删除指定行
        :param sheet_name: 要删除行所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param row_number: 行号，从1开始计数
        :return: 如果删除成功返回True，若工作表不存在、行号无效等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 检查行号是否有效
            if row_number < 1 or row_number > sheet.max_row:
                print(f"指定的行号 {row_number} 超出有效范围")
                return False

            # 删除指定行
            sheet.delete_rows(row_number)
            return True
        except Exception as e:
            print(f"删除行时出现异常，请查看：{e}")
            return False

    # 获取指定sheetname的所有数据，以字典的形式返回
    def get_sheet_all_data(self, sheet_name):
        """
        获取指定sheetname的所有数据，以字典的形式返回，会跳过表头行
        :param sheet_name: 要获取数据的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :return: 返回一个字典，外层字典的键为行号（从2开始计数），值为内层字典，内层字典的键为表头（列名），值为对应单元格的值，若工作表不存在则返回空字典
        """
        all_data = {}
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return all_data

            sheet = self.workbook[sheet_name]
            headers = self.get_sheet_headers(sheet_name)

            # 从第2行开始遍历获取数据并构建字典（跳过表头行）
            for row_num in range(2, sheet.max_row + 1):
                row_data = {}
                row_cells = sheet[row_num]
                for header, cell in zip(headers, row_cells):
                    row_data[header] = cell.value
                all_data[row_num] = row_data

            return all_data
        except Exception as e:
            print(f"获取工作表数据时出现异常，请查看：{e}")
            return all_data

    # 合并指定单元格
    def merge_cells(self, sheet_name, start_row, start_col, end_row, end_col):
        """
        合并指定单元格
        :param sheet_name: 要合并单元格所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数
        :param start_col: 起始单元格所在列号，从1开始计数,可使用"A"
        :param end_row: 结束单元格所在行号，从1开始计数
        :param end_col: 结束单元格所在列号，从1开始计数,可使用"A"
        :return: 如果合并成功返回True，若工作表不存在、行号或列号超出范围等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]

            # 检查行号和列号的有效性
            max_row = sheet.max_row
            max_col = sheet.max_column
            if type(start_col) != int:
                start_col = self.convert_to_number(start_col)
            if type(end_col) != int:
                end_col = self.convert_to_number(end_col)

            if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                print(f"起始单元格的行号或列号超出有效范围")
                return False
            if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                print(f"结束单元格的行号或列号超出有效范围")
                return False

            # 合并单元格
            sheet.merge_cells(start_row=start_row, start_column=start_col,
                              end_row=end_row, end_column=end_col)
            return True
        except Exception as e:
            print(f"合并单元格时出现异常，请查看：{e}")
            return False

    # 修改指定区域字体格式
    def modify_region_font_format(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None,
                                  font_name='宋体', font_size=11, bold=False, italic=False, color='000000'):
        """
        修改指定区域字体格式，按照不同参数情况对工作表相应单元格进行字体格式设置
        :param sheet_name: 要修改字体格式所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param start_col: 起始单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_row: 结束单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_col: 结束单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param font_name: 字体名称，默认值为'宋体'
        :param font_size: 字号，默认值为11
        :param bold: 是否加粗，默认值为False
        :param italic: 是否倾斜，默认值为False
        :param color: 字体颜色，以十六进制字符串表示，默认值为'000000'（黑色）
        :return: 如果修改成功返回True，若工作表不存在、参数不合法等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            # 创建字体格式对象
            font = Font(name=font_name, size=font_size, bold=bold, italic=italic, color=color)

            # 遍历指定区域的单元格并设置字体格式
            for row in range(start_row, end_row + 1):
                for col in range(start_col, end_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.font = font

            return True
        except Exception as e:
            print(f"修改指定区域字体格式时出现异常，请查看：{e}")
            return False

    # 修改指定区域边框
    def modify_region_border(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None,
                             border_style='thin', border_color='000000'):
        """
        修改指定区域边框
        :param sheet_name: 要修改边框所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param start_col: 起始单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_row: 结束单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_col: 结束单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param border_style: 边框样式，可选值如下（不同版本的openpyxl可能支持的略有差异）：
                            - 'thin': 细边框，默认值，为较细的单实线边框样式。
                            - 'thick': 粗边框，为较粗的单实线边框样式，相较于'thin'更醒目。
                            - 'double': 双实线边框，两条平行的实线组成的边框样式，常用于突出显示区域。
                            - 'dashed': 虚线边框，由虚线组成的边框样式，外观上呈现间断的线条效果。
                            - 'dotted': 点线边框，由点组成的边框样式，线条表现为一连串的点。
                            - 'hair': 极细边框，比'thin'边框更细的一种边框样式，较为纤细。
                            - 'medium': 中等边框，粗细程度介于'thin'和'thick'之间的单实线边框样式。
        :param border_color: 边框颜色，以十六进制字符串表示，默认值为'000000'（黑色）
        :return: 如果修改成功返回True，若工作表不存在、参数不合法等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            # 创建边框样式对象
            side = Side(style=border_style, color=border_color)
            border = Border(left=side, right=side, top=side, bottom=side)

            # 遍历指定区域的单元格并设置边框
            for row in range(start_row, end_row + 1):
                for col in range(start_col, end_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.border = border

            return True
        except Exception as e:
            print(f"修改指定区域边框时出现异常，请查看：{e}")
            return False

    # 修改指定区域对齐方式
    def modify_region_alignment(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None,
                                horizontal='general', vertical='bottom', text_rotation=0, wrap_text=False):
        """
        修改指定区域对齐方式
        :param sheet_name: 要修改对齐方式所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param start_col: 起始单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_row: 结束单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_col: 结束单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param horizontal: 水平对齐方式，可选值有'general'（常规对齐，默认值）、'left'（左对齐）、'center'（居中对齐）、
                            'right'（右对齐）、'fill'（填充对齐）、'justify'（两端对齐）、'centerContinuous'（跨列居中对齐），
                            用于设置单元格内容在水平方向上的对齐方式。
        :param vertical: 垂直对齐方式，可选值有'top'（顶端对齐）、'center'（居中对齐）、'bottom'（底端对齐，默认值）、
                          'justify'（两端对齐）、'distributed'（分散对齐），用于设置单元格内容在垂直方向上的对齐方式。
        :param text_rotation: 文本旋转角度，默认值为0，表示不旋转，可传入整数来指定文本顺时针旋转的角度，取值范围通常为0 - 180度。
        :param wrap_text: 是否自动换行，默认值为False，若传入True，则当单元格内容超出单元格宽度时会自动换行显示。
        :return: 如果修改成功返回True，若工作表不存在、参数不合法等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            # 创建对齐方式对象
            alignment = Alignment(horizontal=horizontal, vertical=vertical, text_rotation=text_rotation,
                                  wrap_text=wrap_text)

            # 遍历指定区域的单元格并设置对齐方式
            for row in range(start_row, end_row + 1):
                for col in range(start_col, end_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.alignment = alignment

            return True
        except Exception as e:
            print(f"修改指定区域对齐方式时出现异常，请查看：{e}")
            return False

    # 修改制定区域的背景颜色，默认为透明
    def modify_region_fill_color(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None,
                                 fill_color='FFFFFF'):
        """
        修改指定区域的背景颜色，默认为透明（白色，十六进制表示为'FFFFFF'，等同于透明）
        :param sheet_name: 要修改背景颜色所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param start_col: 起始单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_row: 结束单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_col: 结束单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param fill_color: 填充颜色，以十六进制字符串表示，默认值为'FFFFFF'（白色，无填充效果），例如'FF0000'表示红色
        :return: 如果修改成功返回True，若工作表不存在、参数不合法等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            # 创建填充样式对象
            fill = PatternFill(fill_type="solid", fgColor=fill_color)

            # 遍历指定区域的单元格并设置背景颜色
            for row in range(start_row, end_row + 1):
                for col in range(start_col, end_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.fill = fill

            return True
        except Exception as e:
            print(f"修改指定区域的背景颜色时出现异常，请查看：{e}")
            return False

    # 修改指定区域值格式
    def modify_region_value_format(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None,
                                   format_code='General'):
        """
        修改指定区域值格式
        :param sheet_name: 要修改值格式所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param start_col: 起始单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_row: 结束单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_col: 结束单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param format_code: 值格式代码，默认值为'General'（常规格式），常见的如'0.00'（保留两位小数的数字格式）、
                            'yyyy-mm-dd'（日期格式）、'@'（文本格式）等，不同的格式代码对应不同的数据展示样式。
        :return: 如果修改成功返回True，若工作表不存在、参数不合法等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            # 遍历指定区域的单元格并设置值格式
            for row in range(start_row, end_row + 1):
                for col in range(start_col, end_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.number_format = format_code

            return True
        except Exception as e:
            print(f"修改指定区域值格式时出现异常，请查看：{e}")
            return False

    # 修改指定行的行高
    def modify_specific_row_height(self, sheet_name, target_rows=None, row_height=14.5):
        """
        修改指定行的行高，依据参数情况进行相应行高设置
        :param sheet_name: 要修改行高所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param target_rows: 指定的行号，可以是单个行号（整数），也可以是多个行号组成的列表，行号从1开始计数，若为None则默认对工作表全部行进行操作
        :param row_height: 行高值，单位通常为磅（point），默认值为14.5，按照规则，若传入此方法的该参数为14.5，则进行相应行高设置操作
        :return: 如果修改成功返回True，若工作表不存在、参数类型错误或行号超出范围等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row

            # 处理target_rows为None的情况，将其设置为全部行号的列表
            if target_rows is None:
                target_rows = list(range(1, max_row + 1))
            # 判断target_rows类型，若不是整数或列表则报错并返回False
            elif isinstance(target_rows, int):
                target_rows = [target_rows]
            else:
                if not isinstance(target_rows, list):
                    print("参数target_rows类型错误，应为整数或整数列表")
                    return False

            # 检查行号是否超出有效范围
            for row in target_rows:
                if row < 1 or row > max_row:
                    print(f"行号 {row} 超出工作表有效范围")
                    return False

            # 进行行高修改操作
            for row in target_rows:
                sheet.row_dimensions[row].height = row_height

            return True
        except Exception as e:
            print(f"修改指定行的行高时出现异常，请查看：{e}")
            return False

    # 修改指定列的列宽
    def modify_specific_column_width(self, sheet_name, target_columns=None, column_width=8.36):
        """
        修改指定列的列宽
        :param sheet_name: 要修改列宽所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param target_columns: 指定的列号，可以是单个列号（整数），也可以是多个列号组成的列表，列号从1开始计数，若为None则默认对全部列进行操作
        :param column_width: 列宽值，单位通常为字符个数（大致衡量，实际与字体等因素有关），默认值为8.36，用于设置指定列的宽度
        :return: 如果修改成功返回True，若工作表不存在、参数类型错误或列号超出范围等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_column = sheet.max_column

            # 处理target_columns为None的情况，设置为全部列号的列表
            if target_columns is None:
                target_columns = list(range(1, max_column + 1))
            # 判断target_columns类型，若不是整数或列表则报错并返回False
            elif isinstance(target_columns, int):
                target_columns = [target_columns]
            else:
                if not isinstance(target_columns, list):
                    print("参数target_columns类型错误，应为整数或整数列表")
                    return False

            # 检查列号是否超出有效范围
            for col in target_columns:
                if col < 1 or col > max_column:
                    print(f"列号 {col} 超出工作表有效范围")
                    return False

            # 进行列宽修改操作
            for col in target_columns:
                sheet.column_dimensions[openpyxl.utils.get_column_letter(col)].width = column_width

            return True
        except Exception as e:
            print(f"修改指定列的列宽时出现异常，请查看：{e}")
            return False

    # 清除指定区域格式
    def clear_region_format(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None):
        """
        清除指定区域格式
        :param sheet_name: 要清除格式所在的工作表名称，需要确保该工作表存在于当前操作的Excel工作簿中
        :param start_row: 起始单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param start_col: 起始单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_row: 结束单元格所在行号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :param end_col: 结束单元格所在列号，从1开始计数，可为None（不同情况有不同处理逻辑）
        :return: 如果清除成功返回True，若工作表不存在、参数不合法等情况返回False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            # 遍历指定区域的单元格并清除格式
            for row in range(start_row, end_row + 1):
                for col in range(start_col, end_col + 1):
                    cell = sheet.cell(row=row, column=col)
                    cell.font = openpyxl.styles.Font()  # 清除字体格式，设置为默认字体
                    cell.border = openpyxl.styles.Border()  # 清除边框格式，设置为无边框
                    cell.alignment = openpyxl.styles.Alignment()  # 清除对齐格式，设置为默认对齐方式
                    cell.fill = openpyxl.styles.PatternFill()  # 清除填充格式，设置为无填充

            return True
        except Exception as e:
            print(f"清除指定区域格式时出现异常，请查看：{e}")
            return False

    # dict写入sheet
    def write_dict_to_sheet(self, sheet_name, data_dict):
        """
        把 dict 写入指定 sheet 中，如果 sheet 中的表头没有与 dict 指定的键，就不插入对应的值，只插入有的表头键值
        :param sheet_name: 要写入数据的工作表名称
        :param data_dict: 包含数据的字典
        :return: 写入成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            headers = self.get_sheet_headers(sheet_name)

            max_row = sheet.max_row + 1

            for col_index, header in enumerate(headers, 1):
                if header in data_dict:
                    sheet.cell(row=max_row, column=col_index).value = data_dict[header]

            return True
        except Exception as e:
            print(f"写入字典数据时出现异常，请查看：{e}")
            return False

    # 写入sheet的表头
    def write_headers_to_sheet(self, sheet_name, headers_list):
        """
        写入表头到指定的工作表
        :param sheet_name: 工作表名称
        :param headers_list: 表头列表
        :return: 写入成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            for col_index, header in enumerate(headers_list, 1):
                sheet.cell(row=1, column=col_index).value = header

            return True
        except Exception as e:
            print(f"写入表头时出现异常，请查看：{e}")
            return False

    # 设置打印区域
    def set_print_area(self, sheet_name, start_row=None, start_col=None, end_row=None, end_col=None):
        """
        设置打印区域
        :param sheet_name: 工作表名称
        :param start_row: 起始行号，从 1 开始计数，可为 None（不同情况有不同处理逻辑）
        :param start_col: 起始列号，从 1 开始计数，可为 None（不同情况有不同处理逻辑）
        :param end_row: 结束行号，从 1 开始计数，可为 None（不同情况有不同处理逻辑）
        :param end_col: 结束列号，从 1 开始计数，可为 None（不同情况有不同处理逻辑）
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在")
                return False

            sheet = self.workbook[sheet_name]
            max_row = sheet.max_row
            max_col = sheet.max_column

            # 根据不同参数情况确定行和列的范围
            if start_row is None and start_col is None and end_row is None and end_col is None:
                start_row, start_col = 1, 1
                end_row, end_col = max_row, max_col
            elif start_row is not None and start_col is not None and end_row is not None and end_col is not None:
                if start_row < 1 or start_row > max_row or start_col < 1 or start_col > max_col:
                    print(f"起始单元格的行号或列号超出有效范围")
                    return False
                if end_row < 1 or end_row > max_row or end_col < 1 or end_col > max_col:
                    print(f"结束单元格的行号或列号超出有效范围")
                    return False
            elif start_row is not None and start_col is None and end_row is not None and end_col is None:
                if start_row < 1 or start_row > max_row:
                    print(f"起始或结束单元格的行号超出有效范围")
                    return False
                start_col = 1
                end_col = max_col
            elif start_row is None and start_col is not None and end_row is None and end_col is not None:
                if start_col < 1 or start_col > max_col:
                    print(f"起始或结束单元格的列号超出有效范围")
                    return False
                start_row = 1
                end_row = max_row
            else:
                print("参数不合法，请检查传入的start_row、start_col、end_row、end_col参数")
                return False

            start_cell = openpyxl.utils.get_column_letter(start_col) + str(start_row)
            end_cell = openpyxl.utils.get_column_letter(end_col) + str(end_row)
            sheet.print_area = f"{start_cell}:{end_cell}"
            return True
        except Exception as e:
            print(f"设置打印区域时出现异常: {e}")
            return False

    # 设置打印标题行
    def set_print_titles(self, sheet_name, rows=None, cols=None):
        """
        设置指定工作表的打印标题
        :param sheet_name: 要设置打印标题的工作表名称
        :param rows: 打印标题的行范围，例如 '1:2' 表示第 1 行和第 2 行作为标题行
        :param cols: 打印标题的列范围，例如 'A:B' 表示 A 列和 B 列作为标题列
        :return: 设置成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            if rows:
                sheet.print_title_rows = rows
            if cols:
                sheet.print_title_cols = cols
            return True
        except Exception as e:
            print(f"设置打印标题时出现异常，请查看：{e}")
            return False

    # 在指定工作表的指定单元格插入分页符
    def insert_page_break(self, sheet_name, row=None, col=None):
        """
        在指定工作表的指定单元格插入分页符
        :param sheet_name: 要插入分页符的工作表名称
        :param row: 分页符所在的行号，从 1 开始计数
        :param col: 分页符所在的列号，从 1 开始计数
        :return: 插入成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            if row and col:
                sheet.row_breaks.append(row)
                sheet.column_breaks.append(col)
            elif row:
                sheet.row_breaks.append(row)
            elif col:
                sheet.column_breaks.append(col)
            return True
        except Exception as e:
            print(f"插入分页符时出现异常，请查看：{e}")
            return False

    # 设置打印方向
    def set_print_orientation(self, sheet_name, orientation=1):
        """
        设置指定工作表的打印方向
        :param sheet_name: 要设置打印方向的工作表名称
        :param orientation: 打印方向，1 表示竖向（默认值），2 表示横向
        :return: 设置成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False
            sheet = self.workbook[sheet_name]
            if orientation == 1:
                sheet.page_setup.orientation = sheet.ORIENTATION_PORTRAIT
            elif orientation == 2:
                sheet.page_setup.orientation = sheet.ORIENTATION_LANDSCAPE
            else:
                print("无效的打印方向参数，仅支持 1（竖向）或 2（横向）")
                return False
            return True
        except Exception as e:
            print(f"设置打印方向时出现异常，请查看：{e}")
            return False

    # 设置指定工作表的自定义缩放选项
    def set_custom_zoom(self, sheet_name, option=1):
        """
        设置指定工作表的自定义缩放选项
        :param sheet_name: 要设置缩放选项的工作表名称
        :param option: 缩放选项，1 代表无缩放（默认），2 代表将工作表调整为一页，
                       3 代表将所有列调整为一页，4 代表将所有行调整为一页
        :return: 设置成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False
            sheet = self.workbook[sheet_name]

            sheet.sheet_properties.pageSetUpPr.fitToPage = True

            if option == 1:
                sheet.page_setup.fitToHeight = False
                sheet.page_setup.fitToWidth = False
                sheet.page_setup.scale = 100
            elif option == 2:
                sheet.page_setup.fitToHeight = 1
                sheet.page_setup.fitToWidth = 1
            elif option == 3:
                sheet.page_setup.fitToHeight = False
                sheet.page_setup.fitToWidth = 1
            elif option == 4:
                sheet.page_setup.fitToHeight = 1
                sheet.page_setup.fitToWidth = False
            else:
                print("无效的缩放选项，仅支持 1、2、3、4。")
                return False

            return True
        except Exception as e:
            print(f"设置自定义缩放选项时出现异常，请查看：{e}")
            return False

    # 设置指定工作表的纸张大小
    def set_paper_size(self, sheet_name, paper_size=9):
        """
        设置指定工作表的纸张大小
        :param sheet_name: 要设置纸张大小的工作表名称
        :param paper_size: 纸张规格编号，可参考以下常见编号：
                           1: Letter 纸 (8.5 in. x 11 in., 216 x 279 mm)
                           2: Letter 小纸 (8.5 in. x 11 in., 216 x 279 mm)
                           3: Tabloid 纸 (11 in. x 17 in., 279 x 432 mm)
                           4: Ledger 纸 (17 in. x 11 in., 432 x 279 mm)
                           5: Legal 纸 (8.5 in. x 14 in., 216 x 356 mm)
                           6: Statement 纸 (5.5 in. x 8.5 in., 140 x 216 mm)
                           7: Executive 纸 (7.25 in. x 10.5 in., 184 x 267 mm)
                           8: A3 纸 (11.7 in. x 16.5 in., 297 x 420 mm)
                           9: A4 纸 (8.3 in. x 11.7 in., 210 x 297 mm)
                           10: A4 小纸 (8.3 in. x 11.7 in., 210 x 297 mm)
                           11: A5 纸 (5.8 in. x 8.3 in., 148 x 210 mm)
                           12: B4 纸 (9.8 in. x 13.9 in., 250 x 354 mm)
                           13: B5 纸 (7.0 in. x 10.0 in., 176 x 250 mm)
                           14: Folio 纸 (8.5 in. x 13 in., 216 x 330 mm)
                           15: Quarto 纸 (8.4 in. x 10.8 in., 215 x 275 mm)
                           16: 10 x 14 纸 (10 in. x 14 in., 254 x 356 mm)
                           17: 11 x 17 纸 (11 in. x 17 in., 279 x 432 mm)
                           18: Note 纸 (8.5 in. x 11 in., 216 x 279 mm)
                           19: Envelope #9 (3.875 in. x 8.875 in., 98 x 225 mm)
                           20: Envelope #10 (4.125 in. x 9.5 in., 105 x 241 mm)
                           21: Envelope #11 (4.5 in. x 10.375 in., 114 x 264 mm)
                           22: Envelope #12 (4.75 in. x 11 in., 121 x 279 mm)
                           23: Envelope #14 (5 in. x 11.5 in., 127 x 292 mm)
                           24: C 纸 (17 in. x 22 in., 432 x 559 mm)
                           25: D 纸 (22 in. x 34 in., 559 x 864 mm)
                           26: E 纸 (34 in. x 44 in., 864 x 1118 mm)
                           27: Envelope DL (4.33 in. x 8.66 in., 110 x 220 mm)
                           28: Envelope C5 (6.38 in. x 9.02 in., 162 x 229 mm)
                           29: Envelope C3 (12.99 in. x 18.35 in., 324 x 460 mm)
                           30: Envelope C4 (9.02 in. x 12.99 in., 229 x 324 mm)
                           31: Envelope C6 (4.5 in. x 6.38 in., 114 x 162 mm)
                           32: Envelope C65 (4.5 in. x 9.02 in., 114 x 229 mm)
                           33: Envelope B4 (9.84 in. x 13.9 in., 250 x 353 mm)
                           34: Envelope B5 (7.01 in. x 9.84 in., 176 x 250 mm)
                           35: Envelope B6 (4.92 in. x 7.01 in., 125 x 176 mm)
                           36: Envelope Italy (4.02 in. x 7.56 in., 102 x 191 mm)
                           37: Envelope Monarch (3.875 in. x 7.5 in., 98 x 191 mm)
        :return: 设置成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False
            sheet = self.workbook[sheet_name]
            sheet.page_setup.paperSize = paper_size
            return True
        except Exception as e:
            print(f"设置纸张大小出现异常，请查看：{e}")
            return False

    # 设置页边距
    def set_page_margins(self, sheet_name, left=1.905, right=1.905, top=2.54, bottom=2.54, header=1.27, footer=1.27):
        """
        设置指定工作表的页边距
        :param sheet_name: 要设置页边距的工作表名称
        :param left: 左边距，单位为厘米，默认值为 1.905
        :param right: 右边距，单位为厘米，默认值为 1.905
        :param top: 上边距，单位为厘米，默认值为 2.54
        :param bottom: 下边距，单位为厘米，默认值为 2.54
        :param header: 页眉边距，单位为厘米，默认值为 1.27
        :param footer: 页脚边距，单位为厘米，默认值为 1.27
        :return: 设置成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False

            sheet = self.workbook[sheet_name]
            # 1 厘米约等于 0.393701 英寸
            inch_per_cm = 0.393701
            sheet.page_margins.left = left * inch_per_cm
            sheet.page_margins.right = right * inch_per_cm
            sheet.page_margins.top = top * inch_per_cm
            sheet.page_margins.bottom = bottom * inch_per_cm
            sheet.page_margins.header = header * inch_per_cm
            sheet.page_margins.footer = footer * inch_per_cm

            return True
        except Exception as e:
            print(f"设置页边距时出现异常，请查看：{e}")
            return False

    def insert_image(self, sheet_name, image_path, row, col):
        """
        在指定工作表的指定单元格位置插入图片，并使图片高度与单元格高度一致
        :param sheet_name: 要插入图片的工作表名称
        :param image_path: 图片文件的路径
        :param row: 图片插入的行号，从 1 开始计数
        :param col: 图片插入的列号，从 1 开始计数
        :return: 如果插入成功返回 True，若工作表不存在等情况返回 False
        """
        try:
            if sheet_name in self.list_sheets():
                ws = self.workbook[sheet_name]
                img = Image(image_path)

                # 获取单元格的宽度和高度
                col_letter = openpyxl.utils.get_column_letter(col)
                cell_width = ws.column_dimensions[col_letter].width
                cell_height = ws.row_dimensions[row].height

                # 若宽度或高度为 None，则使用默认值
                default_width = 64
                default_height = 18
                px_per_unit_width = 7
                px_per_unit_height = 1.33

                if cell_width is None:
                    cell_width = default_width
                if cell_height is None:
                    cell_height = default_height

                img.width = int(cell_width * px_per_unit_width)
                img.height = int(cell_height * px_per_unit_height)

                cell_addr = openpyxl.utils.get_column_letter(col) + str(row)
                ws.add_image(img, cell_addr)
                return True
            else:
                print(f"工作簿中不存在名为 {sheet_name} 的 sheet")
                return False
        except Exception as e:
            print(f"插入图片失败，请查看：{e}")
            return False

    def get_merged_cells(self, sheet_name):
        sheet = self.workbook[sheet_name]
        return list(sheet.merged_cells.ranges)

    def unmerge_cells(self, sheet_name, merged_cell):
        sheet = self.workbook[sheet_name]
        sheet.unmerge_cells(range_string=str(merged_cell))

    def insert_hyperlink(self, sheet_name, row, col, text, hyperlink):
        """
        在指定单元格插入超链接
        :param sheet_name: 工作表名称
        :param row: 行号（从 1 开始）
        :param col: 列号（从 1 开始）
        :param text: 超链接显示文本
        :param hyperlink: 超链接地址
        :return: 插入成功返回 True，否则返回 False
        """
        try:
            if sheet_name not in self.list_sheets():
                print(f"工作表 {sheet_name} 不存在于工作簿中")
                return False
            sheet = self.workbook[sheet_name]
            cell = sheet.cell(row=row, column=col)
            cell.value = text
            cell.hyperlink = hyperlink
            cell.style = "Hyperlink"  # 应用超链接样式（可选）
            return True
        except Exception as e:
            print(f"插入超链接失败：{e}")
            return False
